package com.hhd.flow.engine.cmd.impl;

import com.hhd.flow.engine.utils.CommonUtils;
import com.hhd.flow.engine.utils.FlowUtils;
import com.hhd.flow.engine.vo.ApproveType;
import com.hhd.flow.engine.vo.FlowModel;
import com.hhd.flow.entity.*;
import com.hhd.flow.exception.FlowException;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.SuperBuilder;

import java.util.Date;

@Setter
@Getter
@SuperBuilder(toBuilder = true)
public class WithdrawCommand extends FlowUserTaskChangeCommand<Void> {
    private String comment;
    private String processInstanceId;

    //下面是运行时产生的参数
    private FlowProcessInstance flowProcessInstance;
    private FlowComment flowComment;
    private FlowProcessInstanceHistory processInstanceHistory;
    private FlowModel flowModel;

    @Override
    public Void execute() {
        loadFlowProcessInstance();

        createComment();

        beforeWidthdraw();

        check();

        withdraw();

        afterWidthdraw();

        return null;
    }

    private void check() {
        if (Boolean.TRUE.equals(flowProcessInstance.getCannotWidthdraw())) {
            throw new FlowException(getCannotWithdrawMessage());
        }
    }

    private String getCannotWithdrawMessage() {
        String result = "不可撤回";
        if (!CommonUtils.isEmpty(flowProcessInstance.getCannotWithdrawMessage())) {
            result += ", 原因是: " + flowProcessInstance.getCannotWithdrawMessage();
        }
        return result;
    }

    private void beforeWidthdraw() {
        publishBeforeWithdraw(this);
    }

    private void afterWidthdraw() {
        publishAfterWithdraw(this);

        clearFlowUserDone(this.flowProcessInstance.getFormId());
    }

    private void createComment() {
        flowComment = FlowUtils.createWithdrawComment(flowProcessInstance);
        flowComment.setMessage(comment);
        getEngine().getFlowCommentService().save(flowComment);
    }

    private void withdraw() {
        createHistory();

        getEngine().getFlowUserTaskService()
                .lambdaUpdate()
                .eq(FlowUserTask::getProcessInstanceId, processInstanceId)
                .remove();

        getEngine().getFlowGatewayExecutionService()
                .lambdaUpdate()
                .eq(FlowGatewayExecution::getProcessInstanceId, processInstanceId)
                .remove();

        getEngine().getFlowTaskService()
                .lambdaUpdate()
                .eq(FlowTask::getProcessInstanceId, processInstanceId)
                .remove();

        getEngine().getFlowProcessInstanceService()
                .lambdaUpdate()
                .eq(FlowProcessInstance::getId, flowProcessInstance.getId())
                .remove();

        getEngine().getFlowProcessInstanceHistoryService().save(processInstanceHistory);
    }

    private void createHistory() {
        flowProcessInstance.setApprovedType(ApproveType.widthdraw.name());
        flowProcessInstance.setApprovedTypeName(ApproveType.widthdraw.getTitle());
        flowProcessInstance.setApproved(false);
        flowProcessInstance.setFinished(true);
        flowProcessInstance.setEndTime(new Date());
        processInstanceHistory = CommonUtils.copyTo(flowProcessInstance, FlowProcessInstanceHistory.class);
    }

    private void loadFlowProcessInstance() {
        flowProcessInstance = getEngine().getFlowProcessInstanceService().getById(processInstanceId);
        FlowProcessInstanceHistory flowProcessInstanceHistory = getEngine().getFlowProcessInstanceHistoryService().getById(processInstanceId);
        if(!CommonUtils.isEmpty(flowProcessInstanceHistory)) throw new RuntimeException("流程已结束, 不可回退");
        CommonUtils.isEmptyThrow(flowProcessInstance, new FlowException("没有找到流程, 请刷新页面后重试"));

        flowModel = loadFlowModelByProcessInstanceId(flowProcessInstance.getId());
    }
}
